
#import "Box2dWrapper.h"

int32 B2_VELOCITY_ITERATIONS = 8;
int32 B2_POSITION_ITERATIONS = 8;
float32 B2_TIMESTEP = 1.0f / 33.0f;
int32 B2_RATIO = 60.0f; 

// Box2D Note: Make sure that the path to your project does not contain any spaces.

@implementation Box2dWrapper

+ (Box2dWrapper *) getInstance {	
    static Box2dWrapper *box2dWrapper;
	@synchronized (self) {
		if(!box2dWrapper) {
			box2dWrapper = [[Box2dWrapper alloc] init];
            [box2dWrapper setup];
		}
	}	
	return box2dWrapper;
}

- (void) setup {    
    b2Vec2 gravity;
    gravity.Set(0.0f, -9.81f);

    world = new b2World(gravity);    
}

- (b2World* ) getWorld {
    return world;
}

- (void) update {
    world->Step(B2_TIMESTEP, B2_VELOCITY_ITERATIONS, B2_POSITION_ITERATIONS);
    world->ClearForces();     
}

- (b2Body *) createStaticBody: (CGRect) rect {
    b2Body *body;    
    b2BodyDef bodyDef;
    b2PolygonShape itemShape;
    
    int x = rect.origin.x, 
        y = rect.origin.y, 
        w = rect.size.width, 
        h = rect.size.height;
    
    bodyDef.type = b2_staticBody;
    
    bodyDef.position.Set( (x + w/2.0f)/B2_RATIO, -(y + h/2.0f)/B2_RATIO );       
    
    body = [[Box2dWrapper getInstance] getWorld] -> CreateBody(&bodyDef);

    float32 j = w/2;
    float32 k = h/2;
    itemShape.SetAsBox(j/B2_RATIO, k/B2_RATIO);
  
    body->CreateFixture(&itemShape, 0.0f);
    return body;  
}

- (b2Body *) createDynamicBody: (CGRect) rect {
    b2Body *body;    
    b2BodyDef bodyDef;
    b2PolygonShape itemShape;
    b2FixtureDef fixtureDef; 
    
    int x = rect.origin.x, 
        y = rect.origin.y, 
        w = rect.size.width, 
        h = rect.size.height;
    
    bodyDef.type = b2_dynamicBody;
    
    bodyDef.position.Set( (x + w/2.0f)/B2_RATIO, -(y + h/2.0f)/B2_RATIO );    
    
    body = [[Box2dWrapper getInstance] getWorld] -> CreateBody(&bodyDef);
    
    float32 j = w/2.0f;
    float32 k = h/2.0f;
    itemShape.SetAsBox(j/B2_RATIO, k/B2_RATIO);
    
    fixtureDef.shape = &itemShape;
    fixtureDef.density = 1.0f; 
    fixtureDef.friction = 0.103f; 
    fixtureDef.restitution = 0.03f; 

    body->CreateFixture(&fixtureDef);
    
    return body;
} 

@end
